<template>
  <div class="right-bottom-wrap" ref="rightBottomRef">
    <vue-ruler-tool :is-scale-revise="true" v-model="markLines" :parent="true" class="bc" :horizontalLine="false">
      <e-candlestick
        :id="id()"
        :chartData="candlestickData"
        v-if="showCand"
        @q-finished="handleCandlFinished"
        @q-contextmenu="handleCandlContextmenu"
        @q-datazoom="handlDatazoom"
        @q-click="handleCandlClick"
        @q-restore="handleRestore"
      >
        <div slot="right-menu">
          <right-context-menu :showContentmenu="showContentmenu" />
        </div>
      </e-candlestick>
    </vue-ruler-tool>
    <Spin class="kxloading" fix v-show="KXLoading">加载中...</Spin>
    <div ref="areaSelection" class="area-selection" v-show="showAreaSelctionEle" />
  </div>
</template>
<script>
import { nanoid } from 'nanoid'
import {
  merge,
  each,
  keys,
  head,
  last,
  max,
  min,
  get,
  isEqual,
  sortBy,
  slice,
  round,
  isEmpty,
  filter,
  indexOf,
  cloneDeep,
  includes,
  isArray
} from 'lodash'
import { createNamespacedHelpers } from 'vuex'
import VueRulerTool from '@/commons/vueRulerTool'
import RightContextMenu from '../RightContextMenu'
import { candlestickOptions, holidayOptions, lxlyqlOptions, xxlhOptions, slgjOptions } from './chartOptions'
import dayjs from 'dayjs'
const { mapState, mapActions } = createNamespacedHelpers('historyVerify')

export default {
  name: 'history-verify-right-bottom',
  data() {
    return {
      holidayData: {},
      markLines: [],
      candLayout: [],
      candlPosi: [],
      candlStart: 0,
      candlEnd: 100,
      currentCandList: [],
      showContentmenu: undefined,
      showAreaSelctionEle: false,
      areaSelctionEle: null,
      areaSelectionStartX: 0,
      areaSelectionStarty: 0,
      areaSelectionEndX: 0
    }
  },
  watch: {
    markLines() {
      this.nhRangTime()
    },
    KXList() {
      this.currentCandList = this.KXList
    },
    currentMeterId() {
      this.candlStart = 0
      this.candlEnd = 100
      this.markLines = []
    },
    wbsjSelectState() {
      if (this.wbsjSelectState) {
        this.showAreaSelctionEle = true
        this.bindMouseEventByWbsj()
      } else {
        this.removeMouseEventByWbsj()
      }
    },
    loadState() {
      this.markLines = []
    }
  },
  components: {
    VueRulerTool,
    RightContextMenu,
    ECandlestick: () => import('@/commons/charts/ECandlestick')
  },
  beforeDestroy() {
    this.removeClickEvent()
    this.removeMouseEventByWbsj()
  },
  mounted() {
    this.areaSelctionEle = this.$refs['areaSelection']
    this.bindClickEvent()
  },
  computed: {
    ...mapState([
      'KXList',
      'KXLoading',
      'showZero',
      'hasRemoveLines',
      'hasRemoveSolid',
      'qcycstForm',
      'nearAnomalyTimeList',
      'hasNearAnomaly',
      'selectedCandlSerie',
      'currentMeterId',
      'xxlhList',
      'lxlyqlState',
      'lxlyqlDay',
      'xxlhParams',
      'xxlhListIndexs',
      'slgjState',
      'slgjList',
      'wbsjSelectState',
      'loadState',
      'spareGas',
      'spareGasLine'
    ]),
    id() {
      return nanoid
    },
    showCand() {
      return this.KXList && this.KXList.length > 0
    },
    candlestickData() {
      const { xAxisList, seriesList, holidayList, lyqlList } = this.modifyCandData(this.KXList)
      const series = []
      each(seriesList, (item, index) => {
        const { markPoint, seriesData } = item
        series.push({
          data: seriesData,
          markPoint: {
            data: markPoint || []
          }
        })
      })
      series.push(...holidayList)
      const _xxlhData = this.modifyXxlhData()
      series.push(..._xxlhData)
      series.push(...lyqlList)
      return merge({}, candlestickOptions, {
        dataZoom: [
          {
            start: this.candlStart,
            end: this.candlEnd
          },
          {
            start: this.candlStart,
            end: this.candlEnd
          }
        ],
        xAxis: {
          data: xAxisList
        },
        series
      })
    }
  },
  methods: {
    ...mapActions([
      'changeNearAnomalyTimeList',
      'changeSelectedCandlSerie',
      'changeXxlhIndexs',
      'changeSlgjList',
      'changeWbsjSelectState',
      'loadCdrkData',
      'changeCdrkModal',
      'changeSlgjState'
    ]),
    bindClickEvent() {
      this.$refs['rightBottomRef'].addEventListener('click', this.chartClick)
    },
    bindMouseEventByWbsj() {
      this.$refs['rightBottomRef'].addEventListener('mousedown', this.handleMousedown)
      this.$refs['rightBottomRef'].addEventListener('mouseup', this.handleMouseup)
    },
    removeMouseEventByWbsj() {
      this.$refs['rightBottomRef'].removeEventListener('mousedown', this.handleMousedown)
      this.$refs['rightBottomRef'].removeEventListener('mousemove', this.handleMousemove)
      this.$refs['rightBottomRef'].removeEventListener('mouseup', this.handleMouseup)
    },
    removeClickEvent() {
      this.$refs['rightBottomRef'].removeEventListener('click', this.chartClick)
    },
    chartClick(arg) {
      const _data = this.candlPosi
      const _x = arg.offsetX
      let _index = 0
      for (let i = 0; i < _data.length - 1; i++) {
        if (_x >= _data[i] && _x <= _data[i + 1]) {
          _index = i
        }
      }
      const _cData = this.currentCandList[_index]
      if (this.slgjState && _cData) {
        this.moddifySlgjList(_cData[0])
      }
    },
    modifyCandData(list = []) {
      let _currentList = list
      this.holidayData = {}
      let _xAxisList = []
      let _firstSerList = []
      const _twoSerList = []
      const _firstMarkPoint = []
      const _firstData = {}
      const _twoData = {}
      const _serList = []
      this.markLines = []

      if (this.hasRemoveLines) {
        _currentList = this.modifyDataByHasLine(_currentList)
      }
      if (this.hasRemoveSolid) {
        _currentList = this.modifyDataByHasSolid(_currentList)
      }

      each(_currentList, (item, index) => {
        /**
         * _j 是否是确实数据
         * _h 节日标识
         * _i 节日名称
         */
        const [_a, _b, _c, _d, _e, _f, _j, _h, _i] = item
        this.filterHoliday(_a, _h, _i, index)
        _xAxisList.push(_a)
        let color0 = '#ec0000'
        let borderColor0 = '#8A0000'
        let color = '#00da3c'
        let borderColor = '#008F28'
        if (_j) {
          color = '#ff9900'
          color0 = '#ff9900'
          borderColor = '#ff9900'
          borderColor0 = '#ff9900'
          _firstMarkPoint.push({
            name: _a,
            value: _c,
            coord: [_a, _c],
            itemStyle: {
              color: '#ff9900'
            }
          })
        }
        if (_f < 0) {
          color = '#ed141e'
          color0 = '#ed141e'
          borderColor = '#ed141e'
          borderColor0 = '#ed141e'
        }
        if (this.showZero && _f === 0) {
          color = '#ffdb5c'
          color0 = '#ffdb5c'
          borderColor = '#ffdb5c'
          borderColor0 = '#ffdb5c'
        }

        if (this.selectedCandlSerie === _a) {
          color = '#fcfb50'
          color0 = '#fcfb50'
          borderColor = '#fcfb50'
          borderColor0 = '#fcfb50'
        }
        let _value = [_b, _c, _e, _d]
        if (this.spareGas && _f === 0) {
          _value = []
        }
        _firstSerList.push({
          name: _a,
          value: _value,
          itemStyle: {
            color,
            borderColor,
            borderColor0,
            color0
          }
        })
        if (!this.spareGasLine) {
          _twoSerList.push(_f)
        }
      })
      const _max = max(_twoSerList)
      const _min = min(_twoSerList)
      const _holidayList = this.createHolidayList(this.holidayData, _max, _min)
      let _lyqlList = []
      if (this.lxlyqlState) {
        _lyqlList = this.modifyLxlyqlData(_max, _min)
      }
      _firstData.markPoint = _firstMarkPoint
      _firstData.seriesData = _firstSerList
      _twoData.seriesData = _twoSerList
      _serList.push(_firstData, _twoData)
      return {
        xAxisList: _xAxisList,
        seriesList: _serList,
        holidayList: _holidayList,
        lyqlList: _lyqlList
      }
    },
    filterHoliday(date, type, name, index) {
      if (type) {
        if (this.holidayData[type]) {
          this.holidayData[type].value.push(index)
        } else {
          this.holidayData[type] = {
            type,
            name: date,
            aliasName: name,
            value: [index]
          }
        }
      }
    },
    createHolidayList(obj, _max = 10, _min = 0) {
      const _keyList = keys(obj)
      const _holidaySerList = []
      each(_keyList, item => {
        if (Number(item) !== 8) {
          const { value, name, aliasName } = this.holidayData[item]
          const _head = head(value)
          const _last = last(value)
          const _data = [
            {
              name,
              aliasName,
              type: 'holiday',
              value: [_head, _min]
            },
            {
              name,
              type: 'holiday',
              aliasName,
              value: [_head, _max]
            },
            {
              name,
              type: 'holiday',
              aliasName,
              value: [_last, _max]
            },
            {
              name,
              type: 'holiday',
              aliasName,
              value: [_last, _min]
            }
          ]
          _holidaySerList.push(
            merge({}, holidayOptions, {
              name,
              data: _data,
              markPoint: {
                data: [
                  {
                    type: 'max',
                    name,
                    aliasName
                  }
                ]
              }
            })
          )
        }
      })
      return _holidaySerList
    },
    modifyDataByHasLine(list) {
      const _newList = []
      each(list, item => {
        const [_a, _b, _c, , , ...rest] = item
        _newList.push([_a, _b, _c, _c, _b, ...rest])
      })
      return _newList
    },
    modifyDataByHasSolid(list) {
      const { min, max } = this.qcycstForm
      const _newList = []

      each(list, (item, index) => {
        const [_a, , , , , _gas, ...rest] = item
        const _head = head(this.nearAnomalyTimeList)
        const _last = last(this.nearAnomalyTimeList)
        // 处理临近异常
        if (this.hasNearAnomaly && _a >= _head && _a <= _last) {
          _newList.push(item)
        } else {
          // eslint-disable-next-line eqeqeq
          if (_gas != undefined && (_gas < min || _gas > max)) {
            _newList.push([_a, ...new Array(5), ...rest])
          } else {
            _newList.push(item)
          }
        }
      })
      return _newList
    },
    handleCandlFinished(params) {
      let _list = []
      try {
        const { _itemLayouts } = params.getPointPosition({ finder: { seriesIndex: 1 } })
        _list = _itemLayouts
      } catch (error) {
        // do nothing
      }
      if (!isEmpty(_list) && !isEqual(this.candLayout, _list)) {
        this.candLayout = _list
        this.$nextTick(() => {
          this.modifyCandlPos(_list)
        })
      }
    },
    handleCandlContextmenu(params) {
      const {
        name,
        seriesType,
        data: { type, listIndex }
      } = params

      this.changeXxlhIndexs([])
      if (seriesType === 'candlestick') {
        this.showContentmenu = seriesType
        this.changeSelectedCandlSerie(name)
      } else if (seriesType === 'line' && type === 'xxlh') {
        this.showContentmenu = type
        this.modifyXxlhSelecteIndex(listIndex)
      } else {
        this.showContentmenu = undefined
      }
    },
    modifyCandlPos(list = []) {
      const _newList = []
      let _w = 0
      let _nullIdx = []
      each(list, (item, index) => {
        const {
          brushRect: { x, width }
        } = item
        if (!_w) {
          _w = width
        }
        if (!x) {
          _nullIdx.push(index)
        }
        _newList.push(x)
      })
      let _idx = 0
      let _num = 0
      for (let i = 0; i < _newList.length; i++) {
        if (_newList[i]) {
          _idx = i
          _num = _newList[i]
          break
        }
      }
      each(_nullIdx, (item) => {
        const _p = item - _idx
        _newList[item] = _p * _w * 2 + _num
      })
      this.candlPosi = _newList
    },
    nhRangTime() {
      if (this.markLines.length > 2) {
        this.markLines.pop()
      }
      if (this.markLines.length === 2) {
        this.startAndEndTime()
      }
    },
    handlDatazoom(params = {}) {
      const _len = this.KXList.length
      const { batch } = params
      if (batch && isArray(batch)) {
        const { start, end, startValue, endValue } = get(params, 'batch[0]')
        this.candlStart = start != null ? start : (startValue / _len * 100)
        this.candlEnd = end != null ? end : (endValue / _len * 100)
      } else {
        const { start, end } = params
        this.candlStart = start
        this.candlEnd = end
      }
      this.markLines = []
      this.$nextTick(() => {
        this.viewCandList()
      })
    },
    viewCandList() {
      const _len = this.KXList.length
      const _start = round(_len * (this.candlStart / 100))
      const _end = round(_len * (this.candlEnd / 100)) + 1
      this.currentCandList = slice(this.KXList, _start, _end)
      this.$nextTick(() => {
        if (this.markLines.length === 2) {
          this.startAndEndTime()
        } else {
          this.changeNearAnomalyTimeList([])
        }
      })
    },
    startAndEndTime() {
      const _nList = sortBy(this.markLines, item => {
        return item.site
      })
      const [_start, _end] = _nList
      const _startIndex = this.filterPosi(_start.site) + 1
      const _endIndex = this.filterPosi(_end.site)
      this.changeNearAnomalyTimeList([this.currentCandList[_startIndex], this.currentCandList[_endIndex]])
    },
    filterPosi(num) {
      const _data = this.candlPosi
      let _sIdx
      for (let i = 0; i < _data.length - 1; i++) {
        if (num <= _data[0]) {
          _sIdx = 0
          break
        } else if (num >= _data[_data.length - 1]) {
          _sIdx = _data.length - 1
          break
        } else if (num >= _data[i] && num <= _data[i + 1]) {
          _sIdx = i
          break
        }
      }
      return _sIdx
    },
    modifyXxlhData() {
      const _seriesList = []
      each(this.xxlhList, (list, index) => {
        const _serList = []
        each(list, li => {
          const { name, value } = li
          _serList.push({
            name,
            listIndex: index,
            type: 'xxlh',
            value: [name, value]
          })
        })
        let _lineStyle = {}
        if (includes(this.xxlhListIndexs, index)) {
          _lineStyle = {
            color: '#fef200'
          }
        }
        _seriesList.push(
          merge({}, xxlhOptions, {
            data: _serList,
            lineStyle: _lineStyle,
            markPoint: {
              data: [
                {
                  type: 'average',
                  ...this.xxlhParams[index]
                }
              ]
            }
          })
        )
      })
      if (this.slgjList.length > 0) {
        const _serList = []
        each(this.slgjList, (item, index) => {
          const { name, value } = item
          _serList.push({
            name,
            listIndex: index,
            type: 'xxlh',
            value: [name, value]
          })
        })
        const _lastTime = last(_serList).name
        const _lastList = this.filterKxDataByTime(_lastTime)[0]
        _seriesList.push(
          merge({}, slgjOptions, {
            data: _serList,
            markPoint: {
              data: [
                {
                  type: 'max',
                  ...this.xxlhParams[this.xxlhListIndexs[0]],
                  kData: _lastList
                }
              ]
            }
          })
        )
      }
      return _seriesList
    },
    filterKxDataByTime(time) {
      return filter(this.KXList, item => {
        return item[0] === time
      })
    },
    modifyLxlyqlData(_max, _min) {
      const _data = this.KXList
      const _len = _data.length
      let _t
      let _ta
      let _r = []
      for (let i = 0; i < _len; i++) {
        let _c = _data[i]
        if (_c && _c[0] && _c[5] === 0) {
          if (_t === _c[0]) {
            _ta.push(_t)
            _t = dayjs(_t)
              .add(1, 'day')
              .format('YYYY-MM-DD')
            continue
          }
          _ta = [_c[0]]
          _t = dayjs(_c[0])
            .add(1, 'day')
            .format('YYYY-MM-DD')
          _r.push(_ta)
        }
      }
      const _lxlyqlSerList = []
      const type = 'lxlyql'
      each(_r, (item, index) => {
        const _len = item.length
        if (_len >= this.lxlyqlDay) {
          const _head = head(item)
          const _last = last(item)
          const _data = [
            {
              name,
              type,
              value: [_head, _min]
            },
            {
              name,
              type,
              value: [_head, _max]
            },
            {
              name,
              type,
              value: [_last, _max]
            },
            {
              name,
              type,
              value: [_last, _min]
            }
          ]
          _lxlyqlSerList.push(
            merge({}, lxlyqlOptions, {
              name,
              data: _data,
              markPoint: {
                data: [
                  {
                    type: 'max',
                    name
                  }
                ]
              }
            })
          )
        }
      })
      return _lxlyqlSerList
    },
    handleCandlClick(params) {
      const {
        seriesType,
        name,
        data: { type, listIndex }
      } = params
      this.changeSelectedCandlSerie(name)
      if (seriesType === 'line' && type === 'xxlh') {
        this.modifyXxlhSelecteIndex(listIndex)
      }
    },
    filterXxlhSelecteIndex(list, index) {
      return indexOf(list, index)
    },
    modifyXxlhSelecteIndex(index) {
      const _l = cloneDeep(this.xxlhListIndexs)
      const _idx = this.filterXxlhSelecteIndex(_l, index)
      if (_idx === -1 && this.xxlhListIndexs.length > 1) {
        return this.$Notice.warning({
          title: '操作提示',
          desc: '最多支持选择两条线'
        })
      }
      if (_idx > -1) {
        _l.splice(_idx, 1)
      } else {
        _l.push(index)
      }
      if (_l.length === 0) {
        this.changeSlgjState(false)
      }
      this.changeXxlhIndexs(_l)
    },
    moddifySlgjList(time) {
      const _list = this.xxlhList[this.xxlhListIndexs[0]]
      const _lList = last(_list)
      const _hList = head(_list)
      const _xxlhLastTime = _lList.name
      const _xxlhHeadTime = _hList.name
      let _diff = 0
      if (time > _xxlhLastTime) {
        _diff = dayjs(time).diff(dayjs(_xxlhLastTime), 'day')
        const _xxlhListLen = head(this.xxlhList).length
        _diff > 0 && this.createSlgjList(_xxlhLastTime, _diff + _xxlhListLen, _xxlhListLen)
      } else if (time < _xxlhHeadTime) {
        _diff = dayjs(dayjs(_xxlhHeadTime).subtract(1, 'day')).diff(dayjs(time), 'day')
        _diff > 0 && this.createSlgjList(time, 1, 0 - _diff)
      }
    },
    createSlgjList(time, day, startNum) {
      const { k, b } = this.xxlhParams[this.xxlhListIndexs[0]]
      const _list = []
      let j = 0
      for (let i = startNum; i <= day; i++) {
        const _t = dayjs(time)
          .add(j, 'day')
          .format('YYYY-MM-DD')
        _list.push({
          name: _t,
          value: k * i + b
        })
        j++
      }
      this.changeSlgjList(_list)
    },
    handleMousedown() {
      const { offsetX, offsetY } = event
      this.areaSelectionStartX = offsetX
      this.areaSelectionStartY = offsetY
      this.areaSelctionEle.setAttribute('style', `top:${offsetY}px;left:${offsetX}px;`)
      this.$refs['rightBottomRef'].addEventListener('mousemove', this.handleMousemove)
    },
    handleMousemove() {
      this.setAreaSelectionWh(event)
    },
    handleMouseup() {
      this.setAreaSelectionWh(event)
      const { offsetX } = event
      this.$refs['rightBottomRef'].removeEventListener('mousemove', this.handleMousemove)
      this.$Modal.confirm({
        title: '确认提示',
        content: '是否进行C端入口数据引入',
        onOk: () => {
          this.areaSelectionEndX = offsetX
          this.showAreaSelctionEle = false
          this.changeWbsjSelectState(false)
          this.areaSelectionOK()
        }
      })
    },
    setAreaSelectionWh(event) {
      const { offsetX, offsetY } = event
      const _w = offsetX - this.areaSelectionStartX
      const _h = offsetY - this.areaSelectionStartY
      this.areaSelctionEle.style.width = _w + 'px'
      this.areaSelctionEle.style.height = _h + 'px'
    },
    async areaSelectionOK() {
      this.areaSelctionEle.style.width = 0
      this.areaSelctionEle.style.height = 0
      const _startIndex = this.filterPosi(this.areaSelectionStartX - 18) + 1
      const _endIndex = this.filterPosi(this.areaSelectionEndX - 18)
      const _startTime = this.currentCandList[_startIndex] && this.currentCandList[_startIndex][0]
      const _endTime = this.currentCandList[_endIndex] && this.currentCandList[_endIndex][0]
      if (_startTime && _endTime) {
        await this.loadCdrkData({
          startTime: _startTime,
          endTime: _endTime
        })
        this.changeCdrkModal(true)
      }
    },
    handleRestore() {
      this.candlStart = 0
      this.candlEnd = 100
    }
  }
}
</script>
<style lang="less" scoped>
@deep: ~'>>>';

.right-bottom-wrap {
  position: relative;
  width: 100%;
  height: 100%;

  .bc {
    @{deep} .vue-ruler-content {
      width: 100%;
      height: 100%;
      box-sizing: border-box;
    }
  }
  .kxloading {
    z-index: 999;
  }
  .area-selection {
    position: absolute;
    z-index: 1000;
    border: 1px dashed #fff;
    background: rgba(255, 255, 255, 0.5);
    opacity: 0.5;
  }
}
</style>
